package com.zengdada.dml.model;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.zengdada.authority.model.DmlColumn;

import java.sql.Types;
import java.util.HashMap;
import java.util.Map;

public class DmlColumnExtend extends DmlColumn {


    static final Map<String, Integer> SQL_MAP = new HashMap<String, Integer>() {{
        put("bit", Types.BIT);
        put("tinyint", Types.TINYINT);
        put("smallint", Types.SMALLINT);
        put("integer", Types.INTEGER);
        put("bigint", Types.BIGINT);
        put("float", Types.FLOAT);
        put("real", Types.REAL);
        put("double", Types.DOUBLE);
        put("numeric", Types.NUMERIC);
        put("decimal", Types.DECIMAL);
        put("char", Types.CHAR);
        put("varchar", Types.VARCHAR);
        put("longvarchar", Types.LONGVARCHAR);
        put("date", Types.DATE);
        put("time", Types.TIME);
        put("timestamp", Types.TIMESTAMP);
        put("binary", Types.BINARY);
        put("varbinary", Types.VARBINARY);
        put("longvarbinary", Types.LONGVARBINARY);
        put("null", Types.NULL);
        put("other", Types.OTHER);
        put("java_object", Types.JAVA_OBJECT);
        put("distinct", Types.DISTINCT);
        put("struct", Types.STRUCT);
        put("array", Types.ARRAY);
        put("blob", Types.BLOB);
        put("clob", Types.CLOB);
        put("ref", Types.REF);
        put("datalink", Types.DATALINK);
        put("boolean", Types.BOOLEAN);
        put("rowid", Types.ROWID);
        put("nchar", Types.NCHAR);
        put("nvarchar", Types.NVARCHAR);
        put("longnvarchar", Types.LONGNVARCHAR);
        put("nclob", Types.NCLOB);
        put("sqlxml", Types.SQLXML);
        put("ref_cursor", Types.REF_CURSOR);
        put("time_with_timezone", Types.TIME_WITH_TIMEZONE);
        put("timestamp_with_timezone", Types.TIMESTAMP_WITH_TIMEZONE);
    }};

    /**
     * 主键
     */
    public static final int ATTR_PK = 1;
    /**
     * 不能为空
     */
    public static final int ATTR_REQUIRED = 2;
    /**
     * INSERT字段
     */
    public static final int ATTR_INSERTABLE = 4;
    /**
     * UPDATE字段
     */
    public static final int ATTR_UPDATABLE = 8;
    /**
     * 只读，启用后 INSERT_ON/UPDATE_ON 将无效
     */
    public static final int ATTR_READONLY = 16;
    /**
     * 可查询
     */
    public static final int ATTR_QUERYABLE = 32;
    /**
     * 可排序
     */
    public static final int ATTR_SORTABLE = 64;
    /**
     * 可用于分组
     */
    public static final int ATTR_GROUPABLE = 128;

    /**
     * 字段类型
     */
    public static final int ANY_WHERE_COLUMN = -1;
    public static final int SELECT_COLUMN = 0;
    public static final int IN_PARAM_COLUMN = 1;
    public static final int OUT_PARAM_COLUMN = 2;
    public static final int INOUT_PARAM_COLUMN = 3;
    public static final int RET_VALUE_COLUMN = 4;

    private Class<?> dataTypeClass;
    private int sqlType = Types.NULL;
    private String expression;
    private Object defaultValue;
    private Object value;


    public DmlColumnExtend() {
    }

    public DmlColumnExtend(String name, String expression, Class<?> dataTypeClass, int columnType) {
        super();
        setName(name);
        this.expression = expression;
        this.dataTypeClass = dataTypeClass;
        setColumnType(columnType);
        setAttrs(0L);
    }

    // json解析
    public void parseJSON(JSONObject json) {
        try {
            if (json.containsKey(getLabel())) {
                this.value = json.getString(getLabel());
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public DmlColumnExtend(String name, String expression, Class<?> dataType) {
        this(name, expression, dataType, IN_PARAM_COLUMN);
    }

    public Class<?> getDataTypeClass() {
        return dataTypeClass;
    }

    public void setDataTypeClass(Class<?> dataTypeClass) {
        this.dataTypeClass = dataTypeClass;
        super.setDataType(dataTypeClass == null ? null : dataTypeClass.getName());
    }

    public String getExpression() {
        return expression;
    }

    public void setExpression(String expression) {
        this.expression = expression;
    }

    @Override
    public String getLabel() {
        return super.getLabel() == null ? this.getName().replaceAll("[^\\w]", "_") : super.getLabel();
    }

    @Override
    public String getCaption() {
        return super.getCaption() == null ? this.getLabel() : super.getCaption();
    }

    public Object getDefaultValue() {
        return defaultValue;
    }

    public void setDefaultValue(Object defaultValue) {
        this.defaultValue = defaultValue;
    }

    public boolean hasAttr(int flag) {
        return (flag & getAttrs()) == flag;
    }

    public void setAttr(int flag, boolean onOrOff) {
        setAttrs(onOrOff ? getAttrs() | flag : getAttrs() ^ getAttrs() & getAttrs());
    }

    public int getSqlType() {
        return sqlType;
    }

    public void setSqlType(int sqlType) {
        this.sqlType = sqlType;
    }


    @Override
    public void setExtype1(String extype1) {
        super.setExtype1(extype1);
        if (extype1 != null) {
            if (!SQL_MAP.containsKey(extype1))
                throw new IllegalArgumentException(String.format("SQL类型不受支持：%s", extype1));
            setSqlType(SQL_MAP.get(extype1));
        }
    }

    @Override
    public void setDataType(String dataType) {
        super.setDataType(dataType);
        try {
            setDataTypeClass(Class.forName(dataType));
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException(String.format("数据类型错误：%s", e.getMessage()));
        }
    }
}
